<?php
/**
 * CreateTime: 2023/11/15 15:31
 * User:LinQ
 */


namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Support\Facades\Validator as Validator;
use Illuminate\Contracts\Validation\Validator as ValidatorX;

class BasicFormRequests extends FormRequest
{
    /**
     * 当前验证规则
     * @var array
     */
    protected $rule = [];

    /**
     * 验证提示信息
     * @var array
     */
    protected $message = [];

    /**
     * 验证场景定义
     * @var array
     */
    protected $scene = [];

    /**
     * 设置当前验证场景
     * @var array
     */
    protected $currentScene = null;

    /**
     * 验证失败错误信息
     * @var array
     */
    protected $error = [];

    /**
     * 场景需要验证的规则
     * @var array
     */
    protected $only = [];


    /**
     * 设置验证场景
     * @access public
     * @param  string  $name  场景名
     * @return $this
     */
    public function scene($name)
    {
        // 设置当前场景
        $this->currentScene = $name;

        return $this;
    }

    /**
     * 数据验证
     * @access public
     * @param  array     $data  数据
     * @param  mixed     $rules  验证规则
     * @param  array    $message 自定义验证信息
     * @param  string    $scene 验证场景
     * @return bool
     */
    public function check($data, $rules = [], $message = [],$scene = '')
    {

        $this->error =[];

        if (empty($rules)) {
            //读取验证规则
            $rules = $this->rule;
        }
        if (empty($message)) {
            $message = $this->message;
        }

        //读取场景
        if (!$this->getScene($scene)) {
            return false;
        }
        //如果场景需要验证的规则不为空
        if (!empty($this->only)) {
            $new_rules = [];
            foreach ($this->only as $key => $value) {
                // 如果场景配置里存在了 | 可以选择指定规则进行验证
                if(strpos($value, '|') !== false){
                    $arr = explode('|',$value);
                    $f = $arr[0];
                    unset($arr[0]);
                    $newStr = implode("|",$arr);
                    $new_rules[$f] = $newStr;
                }
                if (array_key_exists($value,$rules)) {
                    $new_rules[$value] = $rules[$value];
                }
            }
            $rules = $new_rules;
        }
        $validator = Validator::make($data,$rules,$message);

        //验证失败
        if ($validator->fails()) {
            $this->error = $validator->errors()->first();
            $this->failedValidation($validator);
            return false;
        }

        return !empty($this->error) ? false : true;
    }


    /**
     * 获取数据验证的场景
     * @access protected
     * @param  string $scene  验证场景
     * @return void
     */
    protected function getScene($scene = '')
    {
        if (empty($scene)) {
            // 读取指定场景
            $scene = $this->currentScene;
        }
        $this->only = [];

        if (empty($scene)) {
            return true;
        }

        if (!isset($this->scene[$scene])) {
            //指定场景未找到写入error
            $this->error = "scene:".$scene.'is not found';
            return false;
        }

        // 如果设置了验证适用场景
        $scene = $this->scene[$scene];
        if (is_string($scene)) {
            $scene = explode(',', $scene);
        }
        //将场景需要验证的字段填充入only
        $this->only = $scene;
        return true;
    }

    // 获取错误信息
    public function getError()
    {
        return $this->error;
    }

    // 自定义异常返回
    protected function failedValidation(ValidatorX $validator)
    {
        $error= $validator->errors()->all();
        // 422 Unprocessable Entity
        // 请求无法处理。该状态码通常用于表示表单验证失败，即请求的数据不符合预期的规则或条件。
        throw new HttpResponseException(
            c_return(
                null,
                $error[0],
                status: false,
                code: 'Unprocessable Entity',
                httpCode: 422
            )
        );
    }
}
